package dummy;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.Field;
import java.util.concurrent.Exchanger;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;


public class ScjpTest3 {
	private static Object lock1 = new Object();
	private static Object lock2 = new Object();
	private static Object lock3 = new Object();



	public static void main(final String[] args) throws Exception {		
		
		Field f = Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
		f.setAccessible(true);
		final sun.misc.Unsafe unsafe = (sun.misc.Unsafe)f.get(null);		
		
		
		Runnable r0 = new Runnable() {
			public void run() {
				try {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						//e.printStackTrace();
					}
					synchronized (lock3) {
						for (long i=0;i<=Long.MAX_VALUE-1;i++) {
							if (i%5000000 == 0) {
								//System.out.println("i:"+i);
							}
						}						
					}	
					System.out.println("t0 successfully released lock3");
				} catch (Error e) {
					System.out.println("t0 catched exception: "+e+" "+Thread.currentThread().getState());
				}
			}
		};
				
		//Exchanger ex = new Exchanger();

		final Thread t0 = new Thread(r0);
		t0.start();
		
		Runnable r1 = new Runnable() {
			public void run() {
				try {
				synchronized (lock1) {
					synchronized (lock2) {
						try {							
							lock1.wait();
						} catch (InterruptedException e) {						
							e.printStackTrace();
						}
					}
				}
				System.out.println("t1 finished executions");
				} catch (Exception e) {
					System.out.println("t1 catched exception: "+e+", "+Thread.currentThread().getState());
				}
			}
		};
				
		//Exchanger ex = new Exchanger();

		final Thread t1 = new Thread(new ThreadGroup("tg1"), r1, "t1");
		t1.start();
		Thread.sleep(100);

		Runnable r2 = new Runnable() {
			public void run(){
				synchronized (lock1) {
					System.out.println("T2 etner lock1");
					//synchronized (lock2) {
						try {
							//lock1.notifyAll();
							System.out.println("T2 enter lock2");
							Executors.newSingleThreadExecutor();
							//t0.interrupt();							
							t1.interrupt();							
							System.out.println("T2 interrupt T0,T1");
							Thread.sleep(100);
							System.out.println(t0.getState()+" "+t1.getState());
							t1.stop();							
							//t0.stop();							
							/*synchronized (lock3) {
								System.out.println("Lock3 taked");
							}*/
							Thread.sleep(100);
							System.out.println(t0.getState()+" "+t1.getState());
														
							ThreadMXBean bean = ManagementFactory.getThreadMXBean();
							
							ThreadInfo ti = bean.getThreadInfo(new long[]{t1.getId()}, true, true)[0];							
							System.out.println(t1.getState());							
							unsafe.monitorExit(lock1);
							//unsafe.monitorExit(lock2);
							t0.stop();
							Thread.sleep(100);
							System.out.println(t1.getState());
							
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					//}
				}
			}
		};
		
		
		final Thread t2 = new Thread(r2);
		t2.start();
		
	}
}
